/*
  @Author : lanyulei
*/
// 修改：添加全面的安全机制和初始化保护

package logger

import (
	//"log"
	"os"
	"time"

	"gopkg.in/natefinch/lumberjack.v2"

	"github.com/spf13/viper"
	"go.uber.org/zap"
	"go.uber.org/zap/zapcore"
)

// 全局日志器（现在使用安全的访问方式）
var globalLogger *zap.SugaredLogger

// 回退日志器 - 确保永远不为nil
var fallbackLogger *zap.SugaredLogger

// 初始化回退日志器（包初始化时自动执行）
func init() {
	// 创建安全的回退日志器
	core := zapcore.NewCore(
		zapcore.NewConsoleEncoder(zapcore.EncoderConfig{
			MessageKey:  "msg",
			LevelKey:    "level",
			EncodeLevel: zapcore.CapitalColorLevelEncoder,
			TimeKey:     "time",
			EncodeTime: func(t time.Time, enc zapcore.PrimitiveArrayEncoder) {
				enc.AppendString(t.Format("2006-01-02 15:04:05.000000"))
			},
		}),
		zapcore.AddSync(os.Stderr),
		zapcore.InfoLevel,
	)
	fallbackLogger = zap.New(core).Sugar()
	globalLogger = fallbackLogger // 初始化为回退日志器
}

var levelMap = map[string]zapcore.Level{
	"debug":  zapcore.DebugLevel,
	"info":   zapcore.InfoLevel,
	"warn":   zapcore.WarnLevel,
	"error":  zapcore.ErrorLevel,
	"dpanic": zapcore.DPanicLevel,
	"panic":  zapcore.PanicLevel,
	"fatal":  zapcore.FatalLevel,
}

// Init 初始化日志系统
func Init() {
	// 安全机制：如果 viper 尚未初始化，使用默认值
	if viper.GetString(`settings.log.level`) == "" {
		globalLogger.Warn("Logger configuration not loaded, using fallback settings")
		initDefaultLogger()
		return
	}

	level := getLoggerLevel(viper.GetString(`settings.log.level`))
	var syncWriters []zapcore.WriteSyncer

	// 控制台输出
	if viper.GetBool("settings.log.consoleStdout") {
		syncWriters = append(syncWriters, zapcore.AddSync(os.Stdout))
	}

	// 文件输出
	if viper.GetBool("settings.log.fileStdout") {
		fileConfig := &lumberjack.Logger{
			Filename:   viper.GetString(`settings.log.path`),
			MaxSize:    viper.GetInt(`settings.log.maxsize`),
			MaxAge:     viper.GetInt(`settings.log.maxAge`),
			MaxBackups: viper.GetInt(`settings.log.maxBackups`),
			LocalTime:  viper.GetBool(`settings.log.localtime`),
			Compress:   viper.GetBool(`settings.log.compress`),
		}
		syncWriters = append(syncWriters, zapcore.AddSync(fileConfig))
	}

	// 确保至少有一个输出目标
	if len(syncWriters) == 0 {
		syncWriters = append(syncWriters, zapcore.AddSync(os.Stdout))
	}

	encoderConfig := zap.NewProductionEncoderConfig()
	encoderConfig.EncodeTime = func(t time.Time, enc zapcore.PrimitiveArrayEncoder) {
		enc.AppendString(t.Format("2006-01-02 15:04:05.000000"))
	}

	core := zapcore.NewCore(
		zapcore.NewJSONEncoder(encoderConfig),
		zapcore.NewMultiWriteSyncer(syncWriters...),
		zap.NewAtomicLevelAt(level),
	)

	// 创建带调用者信息的日志器
	logger := zap.New(core, zap.AddCaller(), zap.AddCallerSkip(1))
	globalLogger = logger.Sugar()

	globalLogger.Info("Logger initialized successfully with configuration")
}

// initDefaultLogger 初始化默认日志器
func initDefaultLogger() {
	core := zapcore.NewCore(
		zapcore.NewConsoleEncoder(zapcore.EncoderConfig{
			MessageKey:  "msg",
			LevelKey:    "level",
			EncodeLevel: zapcore.CapitalColorLevelEncoder,
			TimeKey:     "time",
			EncodeTime: func(t time.Time, enc zapcore.PrimitiveArrayEncoder) {
				enc.AppendString(t.Format("2006-01-02 15:04:05.000000"))
			},
		}),
		zapcore.NewMultiWriteSyncer(zapcore.AddSync(os.Stdout)),
		zapcore.InfoLevel,
	)
	logger := zap.New(core, zap.AddCaller())
	globalLogger = logger.Sugar()
	globalLogger.Info("Logger initialized with default settings")
}

func getLoggerLevel(lvl string) zapcore.Level {
	if level, ok := levelMap[lvl]; ok {
		return level
	}
	return zapcore.InfoLevel
}

// 安全获取日志器 - 确保永远不会返回nil
func getLogger() *zap.SugaredLogger {
	if globalLogger == nil {
		// 极端情况下的保护
		return fallbackLogger
	}
	return globalLogger
}

// ==================== 日志方法 ====================
// 所有方法都通过getLogger()获取日志器，确保安全

func Debug(args ...interface{}) {
	getLogger().Debug(args...)
}

func Debugf(format string, args ...interface{}) {
	getLogger().Debugf(format, args...)
}

func Info(args ...interface{}) {
	getLogger().Info(args...)
}

func Infof(format string, args ...interface{}) {
	getLogger().Infof(format, args...)
}

func Warn(args ...interface{}) {
	getLogger().Warn(args...)
}

func Warnf(format string, args ...interface{}) {
	getLogger().Warnf(format, args...)
}

func Error(args ...interface{}) {
	getLogger().Error(args...)
}

func Errorf(format string, args ...interface{}) {
	getLogger().Errorf(format, args...)
}

func DPanic(args ...interface{}) {
	getLogger().DPanic(args...)
}

func DPanicf(format string, args ...interface{}) {
	getLogger().DPanicf(format, args...)
}

func Panic(args ...interface{}) {
	getLogger().Panic(args...)
}

func Panicf(format string, args ...interface{}) {
	getLogger().Panicf(format, args...)
}

func Fatal(args ...interface{}) {
	getLogger().Fatal(args...)
}

func Fatalf(format string, args ...interface{}) {
	getLogger().Fatalf(format, args...)
}
